package com.innovate.nms.service.inspect;

import java.util.List;
import java.util.Map;

import javax.swing.AbstractListModel;

import org.springframework.util.StopWatch;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.eventbus.Subscribe;
import com.innovate.nms.domain.AppConfig;
import com.innovate.nms.domain.InspectHistory;
import com.innovate.nms.domain.NetNode;
import com.innovate.nms.service.channel.Channel;
import com.ivan.toolkit.common.Events;

import lombok.extern.log4j.Log4j;

@Log4j
public class InspectTasks extends AbstractListModel<InspectTask> {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 5916669452699059697L;

	public static InspectTasks me = new InspectTasks();
	
	private List<InspectTask> tasks = Lists.newArrayList();
	
	private Map<Class<? extends InspectTask>, InspectTask> map = Maps.newHashMap();

	private InspectTasks() {
		registerTask(new InspectChannelUdp());
		registerTask(new InspectChannelSms());
		registerTask(new InspectEmsRtu());
		registerTask(new InspectEmsEmu1());
		registerTask(new InspectEmu1Emu2());
		registerTask(new InspectEmu2Emu3());
		registerTask(new InspectEmu3Rtu());
		Events.register(this);
	}
	
	private void registerTask(InspectTask task) {
		task.getPorperty().put("index", tasks.size());
		tasks.add(task);
		map.put(task.getClass(), task);
	}

	@Override
	public int getSize() {
		return tasks.size();
	}

	@Override
	public InspectTask getElementAt(int index) {
		try {
			return tasks.get(index);
		} catch(IndexOutOfBoundsException e) {
			return null;
		}
	}
	
	@Subscribe
	public void dispatchTaskEvent(Events event) {
		
		if(event.keyEqualWith(InspectTask.EventKey)) {
			
			InspectTask source = event.get("source", InspectTask.class);
			if(source == null) return;
			
			int idx = tasks.indexOf(source);
			if(idx != -1) {
				this.fireContentsChanged(this, idx, idx);
			}
			
		}
		
	}
	
	public void clean() {
		
		for(int i = 0; i < tasks.size(); i++) {
			InspectTask t = tasks.get(i);
			t.reset();
			this.fireContentsChanged(this, i, i);
		}
		
	}
	
	public void inspect(int index) {
		
		try {
			InspectTask task = tasks.get(index);
			task.execute();
		} catch(Exception e) {
			
		}
		
	}
	
	public void inspect() {
		
		clean();
		
		try {
			Thread.sleep(500);
		} catch (InterruptedException e1) {
		}
		
		InspectHistory.Entry result = new InspectHistory.Entry();
		result.setTime(System.currentTimeMillis());
		
		StopWatch sw = new StopWatch();
		sw.start();
		
		for(int i = 0; i < tasks.size(); i++) {
			
			InspectTask t = tasks.get(i);
			
			t.run();

		}
		
		sw.stop();
		
		log.info("inspect finished, cost " + sw.getTotalTimeMillis() + " ms");
		
		result.setCost(sw.getTotalTimeMillis());
		
		for(InspectTask task : tasks) {
			result.getValue().put(task.getClass().getSimpleName(), task.getResultString());
		}

		InspectHistory.instance.get().addResult(result);
		
	}
	
	
	class InspectChannelSms extends InspectTask {

		public InspectChannelSms() {
		}
		
		@Override
		public String goal() {
			return String.format("检查无线通道是否准备就绪");
		}

		@Override
		protected Result inspect() throws Exception {
			
			// checking wired channel
			Channel c = Channel.getChannel("SMS");
			if(c != null && c.isReady()) {
				return Result.succeed;
			} else {
				return Result.failed;
			}
			
		}

	}
	
	class InspectChannelUdp extends InspectTask {

		public InspectChannelUdp() {
		}

		@Override
		public String goal() {
			return String.format("检查有线通道是否准备就绪");
		}

		@Override
		protected Result inspect() throws Exception {
			
			// checking wired channel
			Channel c = Channel.getChannel("UDP");
			if(c != null && c.isReady()) {
				return Result.succeed;
			} else {
				return Result.failed;
			}
			
		}

	}

	
	class InspectEmsRtu extends InspectNetTask {

		@Override
		protected NetNode[] initialize() {
			AppConfig config = AppConfig.instance.get();
			return new NetNode[]{config.getRtu()};
		}

	}
	
	class InspectEmsEmu1 extends InspectNetTask {

		@Override
		protected NetNode[] initialize() {
			AppConfig config = AppConfig.instance.get();
			return new NetNode[]{config.getEmu1()};
		}
		
	}	
	
	class InspectEmu1Emu2 extends InspectNetTask {

		@Override
		protected NetNode[] initialize() {
			AppConfig config = AppConfig.instance.get();
			return new NetNode[]{config.getEmu1(), config.getEmu2()};
		}

	}
	
	class InspectEmu2Emu3 extends InspectNetTask {

		@Override
		protected NetNode[] initialize() {
			AppConfig config = AppConfig.instance.get();
			return new NetNode[]{config.getEmu2(), config.getEmu3()};
		}

	}
	
	class InspectEmu3Rtu extends InspectNetTask {

		@Override
		protected NetNode[] initialize() {
			AppConfig config = AppConfig.instance.get();
			return new NetNode[]{config.getEmu3(), config.getRtu()};
		}

	}
	

}
